interface IQueue {
  /** 延时 */
  delay: number;
  /** 优先级 */
  priority: number;
  resolve: () => void;
}

/** 调度器类 */
export class Scheduler {
  /** 最大并发 */
  maxConcurrent: number = 5;
  /** 当前并发 */
  currentConcurrent: number = 0;
  /** 队列 */
  Queue: IQueue[] = [];
  /** 延时id */
  delayIdSet = new Set<number>();
  constructor() {}

  // 开始调度
  startScheduler(maxConcurrent: number = 5) {
    this.maxConcurrent = maxConcurrent;
    this.processScheduler();
  }

  processScheduler() {
    while (this.currentConcurrent < this.maxConcurrent && this.Queue.length > 0) {
      this.currentConcurrent++;
      this.sortQueue();
      const task = this.Queue.shift()!;
      this.executeRequest(task);
    }
  }

  addTask(delay: number, priority: number) {
    return new Promise<void>(resolve => {
      this.Queue.push({delay, priority, resolve});
    });
  }

  cancel() {
    this.Queue = [];
    this.delayIdSet.forEach(timer => clearTimeout(timer));
    this.delayIdSet.clear();
  }

  executeRequest(task: IQueue) {
    const timer = setTimeout(() => {
      task.resolve();
      this.currentConcurrent--;
      this.processScheduler();
      this.delayIdSet.delete(timer);
    }, task.delay);
    this.delayIdSet.add(timer);
  }

  sortQueue() {
    this.Queue.sort((a, b) => b.priority - a.priority);
  }
}
